package com.roobo.common.utils;

import android.os.Environment;
import android.os.IBinder;
import android.util.Log;

import com.roobo.common.utils.ClassReflect;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Utils {

    public static byte[] intToByteArray(int iSource, int iArrayLen) {
        byte[] bLocalArr = new byte[iArrayLen];
        for (int i = 0; (i < 4) && (i < iArrayLen); i++) {
            bLocalArr[i] = (byte) (iSource >> 8 * i & 0xFF);
        }
        return bLocalArr;
    }

    public static int byteToInt(byte[] bRefArr) {
        int iOutcome = 0;
        byte bLoop;

        for (int i = 0; i < bRefArr.length; i++) {
            bLoop = bRefArr[i];
            iOutcome += (bLoop & 0xFF) << (8 * i);
        }
        return iOutcome;
    }

    public static int bytesToInt(byte[] ary, int offset) {
        int value;
        value = (ary[offset] & 0xFF)
                | ((ary[offset + 1] << 8) & 0xFF00)
                | ((ary[offset + 2] << 16) & 0xFF0000)
                | ((ary[offset + 3] << 24) & 0xFF000000);
        return value;
    }

    public static String toHexString(byte[] b) {

        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < b.length; i++) {
            String hex = Integer.toHexString(b[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            sb.append(hex.toUpperCase() + " ");
        }

        return sb.toString();
    }

    public static String toHexString(byte[] b, int offset, int len) {

        StringBuilder sb = new StringBuilder();
        int total_len = b.length;
        if (total_len > offset + len) {
            total_len = offset + len;
        }
        for (int i = offset; i < total_len; i++) {
            String hex = Integer.toHexString(b[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            sb.append(hex.toUpperCase() + " ");
        }

        return sb.toString();
    }

    public static int BUILD_UINT16(byte loByte, byte hiByte) {
        return ((int) (((loByte) & 0x00FF) + (((hiByte) & 0x00FF) << 8)));
    }

    public static byte HI_UINT16(int a) {
        return (byte) (((a) >> 8) & 0xFF);
    }

    public static byte LO_UINT16(int a) {
        return (byte) ((a) & 0xFF);
    }

    public static byte AssicToByte(char x) {
        if (x <= '9' && x >= '0') {
            return (byte) (x - '0');
        } else if (x >= 'a' && x <= 'f') {
            return (byte) (x - 'a' + 10);
        } else if (x >= 'A' && x <= 'F') {
            return (byte) (x - 'A' + 10);
        } else
            return 0;

    }

    public static byte[] StringToBytes(String str) {
        if (str == null || str.length() == 0) {
            return null;
        }
        byte[] data = new byte[str.length()];
        int i = 0;
        int byte_len = 0;
        byte value;
        char x, y;
        while (i < str.length()) {
            x = str.charAt(i);
            if (x != ' ') {
                if (i < str.length() - 1) {
                    y = str.charAt(i + 1);
                    i++;
                } else {
                    y = ' ';
                }

                value = AssicToByte(x);
                if (y != ' ') {
                    value <<= 4;
                    value |= AssicToByte(y);
                }
                data[byte_len++] = value;
            }
            i++;
        }

        byte[] ret_array = new byte[byte_len];
        System.arraycopy(data, 0, ret_array, 0, byte_len);
        return ret_array;
    }

    public static byte[] BytesArrayCopy(byte[] bytes, int len) {
        int arr_len = bytes.length;
        if (arr_len == len) {
            return bytes;
        }
        byte[] ret_array = new byte[len];
        System.arraycopy(bytes, 0, ret_array, 0, len);
        return ret_array;
    }

    /*
     * @param prifex -- prifex of the filename.
     * @param ext    -- the extension of the file name( not include "." ).
     * @return -- the filename what is : prifex + datetime + "." + ext;
     */
    public static String getFileNameDateTime(String prifex, String ext) {
        String fp;
        Date now = new Date();

        // "yyyy-MM-dd_HH-mm-ss"
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");//可以方便地修改日期格式
        String dt = dateFormat.format(now);
        fp = prifex + dt + "." + ext;
        return fp;
    }

    public static String getSDcardDateTimeFilePath(String prifex, String ext) {
        String fp = "";
        File sampleDir = Environment.getExternalStorageDirectory();
        if (!sampleDir.canWrite()) {  // Workaround for broken sdcard support on the device.
            Log.d("HSL", "Can not Write:" + sampleDir.getAbsolutePath());
            sampleDir = new File("/sdcard/sdcard");
        }
        fp = sampleDir.getAbsolutePath() + "/";
        fp = getFileNameDateTime(fp + prifex, ext);

        return fp;
    }

    /*
     * 20170306,get a system property use shell cmd getprop
     */
    public static String getSystemProperty(String propName) {
        String line = null;
        BufferedReader input = null;
        try {

            Process process = Runtime.getRuntime().exec("getprop " + propName);
            InputStreamReader ir = new InputStreamReader(process.getInputStream());
            input = new BufferedReader(ir);
            line = input.readLine();
            input.close();
            if (line.length() == 0) {
                line = null;
            }
        } catch (IOException ex) {
            Log.e("HSL", "Unable to read sysprop " + propName);
            return null;
        }
        return line;
    }

    public static boolean setSystemProperty(String propName, String value) {
        String readbackString;
        try {
            //String line = null;
            //BufferedReader input = null;
            Process process;
            //Runtime.getRuntime().exec("su");
            String cmd = "/system/bin/setprop " + propName + " " + value;
            Runtime.getRuntime().exec(cmd); // Process process =
            //InputStreamReader ir = new InputStreamReader(process.getInputStream());
            //input = new BufferedReader(ir);
            //line = input.readLine();
            //input.close();
            //Log.d("HSL", "setprop:cmd=" + cmd + ",output:" + line);
            readbackString = getSystemProperty(propName);

            if(readbackString != null &&  readbackString.equals(value)){
                return true;
            }

            Log.e("HSL", "setprop-shell:" + propName + " readback=" + readbackString);
        } catch (IOException ex) {
            Log.e("HSL", "Unable to set sysprop " + propName);
            return false;
        }
        return false;
    }

    public static boolean setSystemPropertyReflect(String propName, String value) {
        String className = "android.os.SystemProperties";
        String methodName = "set";
        Method setMethod = ClassReflect.GetClassPublicMethod(className, methodName);
        if( setMethod != null ){
            ClassReflect.invokeMethodArgs(setMethod, propName , value );

            String readbackString = getSystemProperty(propName);

            if(readbackString != null &&  readbackString.equals(value)){
                return true;
            }
            Log.e("HSL", "setprop-java:" + propName + " readback=" + readbackString);
            return false;
        } else {
            Log.d("HSL", "Got SystemProperties.set Method Failed!");
            return false;
        }
    }

    // 20180119,hsl add.
    public static IBinder getSystemServiceReflect(String service) {
        String className = "android.os.ServiceManager";
        String methodName = "getService";
        Method setMethod = ClassReflect.GetClassPublicMethod(className, methodName);
        if( setMethod != null ){
            Object result = ClassReflect.invokeMethodArgs(setMethod, service );

            Log.e("HSL", className + "." + methodName + " return:" + result + ", service = " + service);
            return (IBinder)result;
        } else {
            Log.d("HSL", className + "." + methodName + "--getMethod Failed" + ", service = " + service);
            return null;
        }
    }

    public static String readFileByLines(String fileName) {
        File file = new File(fileName);
        BufferedReader reader = null;
        StringBuilder sb = new StringBuilder();
        try {

            reader = new BufferedReader(new FileReader(file));
            String tempString = null;

            // 一次读入一行，直到读入null为文件结束
            while ((tempString = reader.readLine()) != null) {
                sb.append(tempString);
                sb.append("\n");
            }
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e1) {
                }
            }
        }

        return sb.toString();
    }

    public static void writeFileByLines(String fileName,String content) {
        File file = new File(fileName);
        Writer writer = null;
        try {
            writer = new OutputStreamWriter(new FileOutputStream(file));
            writer.write(content);
            writer.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (writer != null) {
                try {
                    writer.close();
                } catch (IOException e1) {
                }
            }
        }
    }

}
